package com.bw.lib_log.crash;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.os.Looper;
import android.widget.Toast;

import androidx.annotation.NonNull;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @Author : ZhouZiYao
 * @Time : On 2023/11/13 16:39
 * @Description : CrashHandler
 */
public class CrashHandler implements Thread.UncaughtExceptionHandler {
    private final String CRASH_LOG_FILE = "crash_log.txt";
    private Context mContext;
    private Thread.UncaughtExceptionHandler defaultHandler;
    private static CrashHandler instance;
    public static CrashHandler getInstance() {
        if (instance == null) {
            synchronized (CrashHandler.class) {
                if (instance == null) {
                    synchronized (CrashHandler.class){
                        instance = new CrashHandler();
                    }
                }
            }
        }
        return instance;
    }

    private CrashHandler(){

    }

    public void init(Context context){
        mContext = context;
        defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    @Override
    public void uncaughtException(@NonNull Thread t, @NonNull Throwable e) {

        String crashInfo = null;
        try {
            crashInfo = getCrashInfo(t, e);
        } catch (PackageManager.NameNotFoundException ex) {
            throw new RuntimeException(ex);
        }
        String finalCrashInfo = crashInfo;
//        new Thread() {// 在主线程中弹出提示
//            @Override
//            public void run() {
//                Looper.prepare();
//                //自定义对话框弹出堆栈信息
//                showCrashDialog(finalCrashInfo);
//                Looper.loop();
//            }
//        }.start();

        //写入文件
        writeCrashFile(finalCrashInfo);

        //调用默认的 UncaughtExceptionHandler 进行处理
        defaultHandler.uncaughtException(t, e);

    }

    private void showCrashDialog(String crashInfo) {
        Toast.makeText(mContext, ""+crashInfo, Toast.LENGTH_SHORT).show();
    }

    private String getCrashInfo(Thread thread, Throwable throwable) throws PackageManager.NameNotFoundException{
        //实例中只获取了异常的堆栈跟踪信息
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        throwable.printStackTrace(pw);
        pw.flush();
        //时间
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = simpleDateFormat.format(new Date());
        //手机信息
        String phoneInfo = "\n" + "********** Phone Info **********" + "\n" + "\n"
                + "Brand: " + android.os.Build.BRAND + "\n" + "\n" //品牌
                + "Model: " + android.os.Build.MODEL + "\n" + "\n" //型号
                + "SDK: " + android.os.Build.VERSION.SDK_INT + "\n" + "\n" //SDK版本
                + "********** Phone Info **********" + "\n"; //

        PackageManager packageManager = mContext.getPackageManager();
        PackageInfo packageInfo = packageManager.getPackageArchiveInfo(mContext.getPackageName(), 0);
        String versionInfo = "\n" + "********** Version Info **********" + "\n" + "\n"
                + "VersionName: " + packageInfo.versionName + "\n" + "\n"
                + "VersionCode: " + packageInfo.versionCode + "\n" + "\n"
                + "************* Version Info *************" + "\n";

        //可根据需要封装崩溃信息，如线程信息、异常信息、堆栈跟踪
        String crashInfo = "\n" + "********** Crash Log **********" + "\n" + "\n"
                + "CrashTime: " + time + "\n" + "\n" //时间
                + "Thread: " + thread.getName() + "\n" + "\n" //线程名称
                + "ThreadId: " + thread.getId() + "\n" + "\n" //线程id
                + "Exception: " + throwable.getMessage() + "\n" + "\n" //异常信息
                + "Stack Trace: " + sw + "\n" + "\n" //堆栈信息
                + "********** Crash Log **********" + "\n";

        return phoneInfo + versionInfo + crashInfo;
    }

    private void writeCrashFile(String crashInfo) {
        try {
            File file = new File(Environment.getExternalStorageDirectory(), CRASH_LOG_FILE);
            FileWriter fileWriter = new FileWriter(file, true);
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
            bufferedWriter.write(crashInfo);
            bufferedWriter.newLine();
            bufferedWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}